require("coxpcall")
require("cosmo")
require'zdc.nodeapi'
local util = require("zwsapi.util")
local html_forms = require("zwsapi.html_forms")
module(..., package.seeall)
wrappers = {}

-----------------------------------------------------------------------------
-- Creates the HTML for the navigation bar.
--
--  @param node          A node table.
--  @param app       The app object.
--  @return              An HTML string.
-----------------------------------------------------------------------------
function get_nav_bar (node, app)
	assert(node)
	local nav_node = app.dal:GetNode(app.config.DEFAULT_NAVIGATION_BAR)

	local nav = nav_node.content.NAVIGATION
	local navbar={}
	local nodename=node.name or node.__id
	local cur_node = app:dirify(nodename)

	local function matches(id, patterns)
		patterns = patterns or {}
		for i, pattern in ipairs(patterns) do
			if id:match(pattern) then
				return true
			end
		end
	end

	local function remove_quotes(value)
		return value:gsub("'", ""):gsub('"', ''):gsub("%s+", " ")
	end

	local categories = {}

	for i, section in ipairs(nav) do
		if not getmetatable(section) then setmetatable(section,{__metatable=true}) end
		local tsec={}
		navbar[i]=tsec
		tsec.title = section.title or section.id
		categories[section.id] = section.title
		tsec.accessibility_title = remove_quotes(section.title)
		tsec.id	 = app:dirify(section.id)
		tsec.link  = app:make_link(section.id)
		tsec.class = "back"
		tsec.subsections = tsec
		if tsec.id == cur_node or tsec.id == node.category 
			or matches(nodename, section.patterns) then
			tsec.class = "front"
			tsec.accessibility_title = tsec.accessibility_title.." (current section)"
			navbar.current_section = tsec
		end
		for j, subsection in ipairs(section) do
			if not getmetatable(subsection) then setmetatable(subsection,{__metatable=true}) end
			local tsubsec={}
			tsec[j]=tsubsec
			tsubsec.title = subsection.title or subsection.id
			categories[subsection.id] = subsection.title
			tsubsec.accessibility_title = remove_quotes(subsection.title)
			tsubsec.id = app:dirify(subsection.id)
			tsubsec.class = "back"
			tsubsec.link = app:make_link(subsection.id)
			if tsubsec.id == cur_node or tsubsec.id == app:dirify(node.category)
				or matches(nodename, subsection.patterns) then
				tsec.class = "front"
				navbar.current_section = section
				tsubsec.class = "front"
				tsubsec.accessibility_title = tsubsec.accessibility_title.." (current subsection)"
			end
		end
	end

	local default_navsection = app.config.DEFAULT_NAVSECTION
	if not navbar.current_section and default_navsection and nav[default_navsection] then
		navbar[default_navsection].class = "front"
	end

	return navbar, categories
end

function get_breadcrumbs(node, app)
	local breadcrumbs = {}
	
	--do return breadcrumbs end;
	local path = ""
	local not_first
	for i, part in ipairs{util.split(node.name or node.__id, "/")} do
		path = path..part
		local b_node
		if path == node.__id then
			b_node = node
		else
			b_node = app.dal:GetNode(path) or {}
		end
		--local crumb = zdc.doc.get_doc(b_node._doc,'disp') or part
		local crumb = part
		if b_node.breadcrumb and b_node.breadcrumb:match("%S") then
			crumb = b_node.breadcrumb
		end
		table.insert(breadcrumbs, {
			link = app:make_link(path),
			title = crumb,
			_template = not_first and 2
		})
		not_first = true
		path = path.."/"
	end
	return breadcrumbs
end
-----------------------------------------------------------------------------
-- Wraps the HTML content in bells and whistles such as the navigation bar, the header, the footer,
-- etc.
-----------------------------------------------------------------------------
function wrappers.default(user,dal,node,act,request)
	local app=dal.APP or dal
	if request.params.skip_wrapper then
		return node.inner_html
	end

	if request.params.use_wrapper=='content' then
		return wrappers.content(user,dal,node,act,request)
	end 

	if request.auth_message then
		node:post_error(node.translator.translate_key(request.auth_message))
	end

	local is_old = false

	local nav_sections, nav_subsections = get_nav_bar(node, app)

	local translate = node.translator.translate

	local user_link = app:make_link_to_user(request.user)

	local values = {
		site_title		 = app.config.SITE_TITLE or "",
		site_subtitle		 = app.config.SITE_SUBTITLE or "",
		title				= app:escape(node.title),
		title2=node.html_title or app:escape(node.title or '???'),
		if_no_index		= cosmo.c((not request.is_indexable) or is_old){},
		do_css_links	  = node.css_links,
		do_css_snippets  = node.css_snippets,
		do_javascript_links = node.javascript_links,
		do_javascript_snippets  = node.javascript_snippets,
		if_old_version	=cosmo.c(is_old){
									 version		= request.params.version,
								 },
		logout_link		=app:make_link(app.config.LOGOUT_NODE, nil, {next = node.name},
														 nil, {do_not_highlight_missing = true}),
		login_link		=app:make_link(app.config.LOGIN_NODE, nil, {next = node.name},
														 nil, {do_not_highlight_missing=true}),
		register_link	=app:make_link(app.config.REGISTRATION_NODE),
		chgpwd_link		=app:make_link(app.config.CHGPWD_NODE, nil, {next = node.name},
														 nil, {do_not_highlight_missing = true}),
		if_logged_in	  = cosmo.c(request.user){
									 user = app:escape(request.user),
									 if_user_link = cosmo.c(user_link){
										 link = user_link
									 }
								 },
		if_not_logged_in = cosmo.c(not request.user){},
		if_search		  = cosmo.c(app.config.SEARCH_PAGE){},
		base_url			= app.config.BASE_URL,
		search_page		= app.config.SEARCH_PAGE,
		search_box_content = app.config.SEARCH_CONTENT or "", 
		content			 = node.inner_html,
		sidebar			 = "",
		do_messages		= node.messages,

		do_nav_sections  = nav_sections,
		do_nav_subsections = nav_sections.current_section,
		do_breadcrumb	 = get_breadcrumbs(node, app),
		if_multipart_id  = cosmo.c(node.__id:match("/")){},

		-- "links" include "href="
		show_link		  = app:make_link(node.name or node.__id),
		icon_base_url	 = app.config.ICON_BASE_URL or app.config.NICE_URL,
		css_base_url	  = app.config.CSS_BASE_URL or app.config.NICE_URL,
		js_base_url		= app.config.JS_BASE_URL or app.config.NICE_URL,
		do_toolbar		 = function(args)
									 local icons = app.config.TOOLBAR_ICONS
									 for i, command in ipairs(app.config.TOOLBAR_COMMANDS) do
										 if node:__check_acl(request.user, command) then
											 local icon = icons[command]
											 cosmo.yield{
												 link = app:make_link(request.usenode or node.name or node.__id, command),
												 title = translate("_("..command:upper()..")"),
												 command = command,
												 if_icon = cosmo.c(icon){ icon = icon },
												 if_text = cosmo.c(not icon){},
											 }
										 end
									 end
								 end,
		--node_rss_link	 = app:make_link(node.__id, "rss"),
		--site_rss_link	 = app:make_link(app.config.HISTORY_PAGE, "rss"),
		-- urls are just urls
		make_url			= function(args)
									 return app:make_url(unpack(args))
								 end,
		base_url			= app.config.BASE_URL, -- for mods
		nice_url			= app.config.NICE_URL, -- for mods
		home_page_url	 = app.config.HOME_PAGE_URL,
		logo_url			= app.config.LOGO_URL,
		favicon_url		= app.config.FAVICON_URL,
		-- icons are urls of images
		if_title_icon	 = cosmo.c(node.icon and node.icon~=""){title_icon = app:make_url(node.icon)},
	}

	for k, v in pairs(node._fds) do
		values[k] = values[k] or node[k]
	end

	local function translate_and_fill(template, values)
		return cosmo.fill(node.translator.translate(template), values)
	end

	values.head = translate_and_fill(node.html_head, values)
	values.menu = translate_and_fill(node.html_menu, values)
	values.logo = translate_and_fill(node.html_logo, values)
	values.search = translate_and_fill(node.html_search, values)
	values.page = translate_and_fill(node.html_page, values)
	values.sidebar = translate_and_fill(node.html_sidebar, values)
	values.header = translate_and_fill(node.html_header, values)
	values.footer = translate_and_fill(node.html_footer, values)
	values.body = translate_and_fill(node.html_body, values)

	return cosmo.fill(node.html_main, values), "text/html"
end
function wrappers.content(user,dal,node,act,request)
	local app=dal.APP or dal
	if request.params.skip_wrapper then
		return node.inner_html
	end

	if request.auth_message then
		node:post_error(node.translator.translate_key(request.auth_message))
	end

	local is_old = false

	local translate = node.translator.translate

	local values = {
		site_title		 = app.config.SITE_TITLE or "",
		site_subtitle		 = app.config.SITE_SUBTITLE or "",
		title				= app:escape(node.title),
		title2=node.html_title or app:escape(node.title or '???'),
		if_no_index		= cosmo.c((not request.is_indexable) or is_old){},
		do_css_links	  = node.css_links,
		do_css_snippets  = node.css_snippets,
		do_javascript_links = node.javascript_links,
		do_javascript_snippets  = node.javascript_snippets,
		if_old_version	= cosmo.c(is_old){
									 version		= request.params.version,
								 },
		base_url			= app.config.BASE_URL,
		content			 = node.inner_html,
		do_messages		= node.messages,

		-- "links" include "href="
		show_link		  = app:make_link(node.name or node.__id),
		icon_base_url	 = app.config.ICON_BASE_URL or app.config.NICE_URL,
		css_base_url	  = app.config.CSS_BASE_URL or app.config.NICE_URL,
		js_base_url		= app.config.JS_BASE_URL or app.config.NICE_URL,
		--node_rss_link	 = app:make_link(node.__id, "rss"),
		--site_rss_link	 = app:make_link(app.config.HISTORY_PAGE, "rss"),
		-- urls are just urls
		make_url			= function(args)
									 return app:make_url(unpack(args))
								 end,
		base_url			= app.config.BASE_URL, -- for mods
		nice_url			= app.config.NICE_URL, -- for mods
		home_page_url	 = app.config.HOME_PAGE_URL,
		logo_url			= app.config.LOGO_URL,
		favicon_url		= app.config.FAVICON_URL,
		-- icons are urls of images
		if_title_icon	 = cosmo.c(node.icon and node.icon~=""){title_icon = app:make_url(node.icon)},
	}

	for k, v in pairs(node._fds) do
		values[k] = values[k] or node[k]
	end

	local function translate_and_fill(template, values)
		return cosmo.fill(node.translator.translate(template), values)
	end

	values.head = translate_and_fill(node.html_head, values)
	values.body = node.inner_html

	return cosmo.fill(node.html_main, values), "text/html"
end
